Soft Delete Strategy
contents
데이터베이스 설계에서 자주 사용되는 Soft Delete(논리적 삭제) 전략에 대한 가이드입니다.
1. Soft Delete란 무엇인가?
Soft Delete는 데이터 삭제 요청이 있을 때, 데이터베이스에서 실제로 데이터를 지우지 않고 "삭제됨"이라는 표시(Flag) 만 남겨두는 전략입니다.
- Hard Delete (물리적 삭제):
DELETE FROM Users WHERE id = 1;- 데이터가 영구적으로 사라집니다.
- Soft Delete (논리적 삭제):
UPDATE Users SET is_deleted = true WHERE id = 1;- 데이터는 남아있지만, 애플리케이션은 마치 없는 것처럼 취급합니다.
2. 구현 패턴 (Implementation Patterns)
가장 흔한 세 가지 방식이 있습니다.
패턴 A: Boolean Flag (단순형)
is_deleted 컬럼(True/False)을 추가합니다.
- 활성:
0(False) - 삭제:
1(True) - 장점: 이해하기 쉽습니다.
- 단점: "언제" 삭제되었는지 알 수 없습니다.
패턴 B: Timestamp (표준형)
deleted_at 컬럼(날짜/시간)을 추가합니다.
- 활성:
NULL - 삭제:
2024-01-24 10:00:00 - 장점: 감사(Audit) 기록이 남습니다(언제 지워졌는지 알 수 있음).
- 단점: SQL 조건이 약간 더 깁니다 (
IS NOT NULLvsIS NULL). - 결론: 이것이 현재의 업계 표준(Standard) 방식입니다.
패턴 C: 상태 Enum (상태 머신)
status 컬럼을 사용합니다.
- 값:
'ACTIVE','INACTIVE','BANNED','DELETED'. - 장점: 복잡한 수명 주기를 가진 데이터에 적합합니다 (예: 주문 취소는 사실상 Soft Delete임).
3. 왜 Soft Delete를 사용하는가? (장점)
-
데이터 복구 (실수 방지):
- 사용자가 중요한 문서를 실수로 삭제했을 때,
deleted_at = NULL로 설정하면 즉시 복구할 수 있습니다.
- 사용자가 중요한 문서를 실수로 삭제했을 때,
-
감사 및 규정 준수 (Auditing):
- 금융이나 의료 분야에서는 삭제된 기록도 일정 기간 보관해야 하는 법적 의무가 있는 경우가 많습니다.
-
데이터 분석 (Analytics):
- 과거 추세를 분석할 수 있습니다. 예: "지난달에 몇 명이 탈퇴했는가?" Hard Delete를 하면 이 정보를 알 수 없습니다.
-
참조 무결성 (Foreign Key 보호):
- "상품"을 Hard Delete 해버리면, 그 상품을 구매했던 과거 "주문 내역"들이 깨질 수 있습니다. Soft Delete는 상품 정보를 남겨두므로 과거 주문 내역이 유효하게 유지됩니다.
4. 숨겨진 위험요소 (단점 및 고려사항)
Soft Delete는 쉬워 보이지만, 엔지니어링 측면에서 상당한 오버헤드를 발생시킵니다.
A. 쿼리 복잡성
애플리케이션의 모든 조회 쿼리에 필터 조건을 넣어야 합니다.
- 전:
SELECT * FROM Users - 후:
SELECT * FROM Users WHERE deleted_at IS NULL - 위험: 개발자가 깜빡하고 이 조건을 빼먹으면, 삭제된 데이터가 보고서나 이메일, UI에 노출되는 사고가 발생합니다.
B. Unique Key 충돌
- User A(
a@b.com)가 Soft Delete 된 상태에서, 새로운 User B가a@b.com으로 가입하려 하면, 실제 데이터는 남아있기 때문에 Unique Constraint 위반이 발생합니다. (부분 인덱스로 해결 필요).
C. 성능 저하 (Bloat)
- 테이블 크기: 테이블이 계속 커지기만 하고 줄어들지 않습니다.
- 인덱스 성능: 인덱스 안에 "죽은 데이터"가 가득 찹니다. 테이블의 90%가 삭제된 데이터라면, DB는 쓸모없는 정보를 캐싱하느라 메모리를 낭비하게 됩니다.
D. GDPR / 개인정보보호 ("잊혀질 권리")
- GDPR 등은 사용자가 삭제를 요청하면 개인정보(PII)를 실제로 파기할 것을 요구합니다.
- 충돌: Soft Delete는 데이터를 보관합니다.
- 해결: 통계를 위해 Soft Delete를 하되, 이름이나 이메일 같은 식별 정보는 "익명화(Anonymize)"(랜덤 문자로 덮어쓰기) 처리해야 합니다.
5. 관계 처리 (Cascading Issue)
가장 골치 아픈 부분입니다. 만약 회사(Company) 를 Soft Delete 하면 소속된 직원(Employees) 들은 어떻게 될까요?
- 방식 1: 애플리케이션 로직 처리 (Join)
- 회만 지우고 직원은 둡니다.
- 직원을 조회할 때마다 회사를 Join 해서 확인합니다:
WHERE Company.deleted_at IS NULL. - 단점: 쿼리가 느려지고 복잡해집니다.
- 방식 2: 연쇄 Soft Delete (Cascading)
- 회사를 지울 때 코드에서 for 문을 돌며 직원들도 다 Soft Delete 처리합니다.
- 단점: 복구가 악몽입니다. 회사를 복구할 때 직원도 다 복구해야 할까요? 만약 회사 삭제 전에 해고당한 직원이 있었다면 그 사람은 어떻게 구분할까요?
6. 대안: "아카이브 테이블(Archive Table)" 전략
데이터 양이 방대하고 성능이 중요하다면, 일반적인 Soft Delete 대신 Archive 패턴을 고려하세요.
작동 방식:
삭제 요청이 오면:
- 트랜잭션 시작.
INSERT INTO Users_Archive SELECT * FROM Users WHERE id = 1;(데이터를 역사관 테이블로 복사).DELETE FROM Users WHERE id = 1;(메인 테이블에서는 Hard Delete).- 트랜잭션 커밋.
- 장점: 메인
Users테이블이 항상 작고 빠릅니다. Unique Key 문제도 자연스럽게 해결됩니다. - 단점: 활성 데이터와 삭제된 데이터를 한 번에 조회(
JOIN)하기가 어렵습니다.
references